/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	SiteMenuItemCmpst.java
 * 模块说明：	
 * 修改历史：
 * Dec 27, 2007 - lxm - 创建。
 */
package com.hd123.rumba.gwt.entry.client;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LoadListener;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.gwtext.client.widgets.MessageBox;
import com.hd123.rumba.gwt.base.client.exception.ClientBizException;
import com.hd123.rumba.gwt.base.client.util.GWTUtil;
import com.hd123.rumba.gwt.entry.client.menu.QMenu;
import com.hd123.rumba.gwt.entry.client.menu.QMenuItem;

/**
 * 左边菜单项 | 界面部件
 * 
 * @author lxm
 * 
 */
class SiteMenuItemCmpst extends Composite {

  /**
   * 构造函数。
   * 
   * @param wUpperMenu
   *          指定所属上级菜单部件。
   */
  public SiteMenuItemCmpst(SiteMenuCmpst wUpperMenu) {
    super();
    assert wUpperMenu != null;
    this.wUpperMenu = wUpperMenu;
    this.expanded = false;
    this.hot = false;
    this.down = false;
    drawSelf();
  }

  /** 所属上级菜单部件 */
  private SiteMenuCmpst wUpperMenu;
  /** 对应的菜单项 */
  private QMenuItem menuItem;
  /** 子菜单 */
  private SiteMenuCmpst wSubMenu;
  /** 标记当前菜单是否是展开状态。 */
  private boolean expanded;
  /** 标记当前菜单项是否是热状态 */
  private boolean hot;
  /** 标记当前菜单项是否是被按下状态 */
  private boolean down;
  /** 标记当前菜单项的打开新窗口按钮是否是热的状态 */
  private boolean hot_newWindow;
  /** 标记当前菜单项的打开新窗口按钮是否是被按下状态 */
  private boolean down_newWindow;

  /** 菜单是否被展开 */
  public boolean isExpanded() {
    return expanded;
  }

  /** 对应的菜单项 */
  public QMenuItem getMenuItem() {
    return menuItem;
  }

  /** 对应的菜单项 */
  public void setMenuItem(QMenuItem menuItem) throws ClientBizException {
    this.menuItem = menuItem;
    refresh();
  }

  /** 子菜单 */
  public SiteMenuCmpst getWSubMenu() {
    return wSubMenu;
  }

  /** 所属上级菜单部件 */
  public SiteMenuCmpst getWUpperMenu() {
    return wUpperMenu;
  }

  /**
   * 取得当前对应的菜单。
   * 
   * @return
   */
  public QMenu getMenu() {
    assert this.wUpperMenu != null;
    return this.wUpperMenu.getMenu();
  }

  /**
   * 取得所属模块入口点。
   * 
   * @return
   */
  public MainFrame getEntryPoint() {
    assert this.wUpperMenu != null;
    return this.wUpperMenu.getEntryPoint();
  }

  /**
   * 取得所属位于根的菜单部件。
   * 
   * @return
   */
  public SiteMenuCmpst getWMenu() {
    return wUpperMenu.getWMenu();
  }

  /**
   * 展开当前菜单项。
   * 
   * @throws ClientBizException
   */
  public void expand() throws ClientBizException {
    if (pnlSubMenu == null)
      return;
    this.expanded = true;
    imgPoint.setUrl(this.getPointImageUrl(this.getMenu()));
    pnlSubMenu.setVisible(this.expanded);
  }

  /**
   * 折叠当前菜单项。将同时折叠所有子菜单。
   * 
   * @throws ClientBizException
   */
  public void collapse() throws ClientBizException {
    if (pnlSubMenu == null)
      return;
    this.expanded = false;
    imgPoint.setUrl(this.getPointImageUrl(this.getMenu()));
    pnlSubMenu.setVisible(this.expanded);
    wSubMenu.collapseAll();
  }

  /** 标记当前菜单项是否是被按下状态 */
  public boolean isDown() {
    return down;
  }

  /** 标记当前菜单项是否是被按下状态 */
  public void setDown(boolean down) {
    if (this.down == down)
      return;
    this.down = down;
    refreshDisplayState();
  }

  /** 标记当前菜单项是否是热状态 */
  public boolean isHot() {
    return hot;
  }

  /** 标记当前菜单项是否是热状态 */
  public void setHot(boolean hot) {
    if (this.hot == hot)
      return;
    this.hot = hot;
    refreshDisplayState();
  }

  /** 标记当前菜单项的打开新窗口按钮是否是被按下状态 */
  public boolean isDown_newWindow() {
    return down_newWindow;
  }

  /** 标记当前菜单项的打开新窗口按钮是否是被按下状态 */
  public void setDown_newWindow(boolean down_newWindow) {
    if (this.down_newWindow == down_newWindow)
      return;
    this.down_newWindow = down_newWindow;
    refreshDisplayState();
  }

  /** 标记当前菜单项的打开新窗口按钮是否是热的状态 */
  public boolean isHot_newWindow() {
    return hot_newWindow;
  }

  /** 标记当前菜单项的打开新窗口按钮是否是热的状态 */
  public void setHot_newWindow(boolean hot_newWindow) {
    if (this.hot_newWindow == hot_newWindow)
      return;
    this.hot_newWindow = hot_newWindow;
    refreshDisplayState();
  }

  /* --- 以下为界面部件 --- */

  /** 整个菜单项界面框架 */
  private VerticalPanel pnl;
  /** 菜单项部分界面框架 */
  private HorizontalPanel pnlItem;
  /** 菜单项节点。 */
  private Image imgPoint;
  /** 菜单项图标。 */
  private Image imgIcon;
  /** 菜单项标题 */
  private HTML htmlCaption;
  /** 菜单项新窗口中打开按钮 */
  private Image imgNewWindow;
  /** 子菜单部分界面框架 */
  private HorizontalPanel pnlSubMenu;
  /** 子菜单缩进 */
  private Label lblIndent;

  /** imgIcon的默认图片URL。 */
  private static final String URL_ICON_DEFAULT = "images/module.gif";
  /** imgNewWindow的图片URL。 */
  private static final String URL_NEWWINDOW = "images/newWindow.gif";
  /** imgNewWindow的图片URL。 */
  private static final String URL_NEWWINDOW_BLANK = "images/newWindow-blank.gif";

  /** imgIcon的事件侦听器 */
  private class Listener_imgIcon implements LoadListener {

    public void onError(Widget sender) {
      imgIcon.setUrl(URL_ICON_DEFAULT);
    }

    public void onLoad(Widget sender) {
      // Do Nothing
    }

  }

  /** 菜单项的事件侦听器。应用于imgPoint, imgIcon, htmlCaption */
  private class Listener_menuItem implements ClickListener, MouseListener {

    public void onClick(Widget sender) {
      click(false);
    }

    public void onMouseDown(Widget sender, int x, int y) {
      mouseDown();
    }

    public void onMouseEnter(Widget sender) {
      mouseEnter();
    }

    public void onMouseLeave(Widget sender) {
      mouseLeave();
    }

    public void onMouseMove(Widget sender, int x, int y) {
      // Do Nothing
    }

    public void onMouseUp(Widget sender, int x, int y) {
      mouseUp();
    }

  }

  /** 菜单项的事件侦听器。 */
  private Listener_menuItem lstnItem;

  /** 新窗口中打开按纽imgNewWindow的事件侦听器。 */
  private class Listener_imgNewWindow implements ClickListener, MouseListener {

    public void onClick(Widget sender) {
      click(true);
    }

    public void onMouseDown(Widget sender, int x, int y) {
      mouseDown_newWindow();
    }

    public void onMouseEnter(Widget sender) {
      mouseEnter_newWindow();
    }

    public void onMouseLeave(Widget sender) {
      mouseLeave_newWindow();
    }

    public void onMouseMove(Widget sender, int x, int y) {
      // Do Nothing
    }

    public void onMouseUp(Widget sender, int x, int y) {
      mouseUp_newWindow();
    }

  }

  /** 新窗口中打开按钮的事件侦听器 */
  private Listener_imgNewWindow lstnNewWindow;

  private void drawSelf() {
    pnl = new VerticalPanel();
    pnl.setWidth("100%");
    this.initWidget(pnl);
  }

  /** 刷新菜单项的显示。 */
  private void refresh() throws ClientBizException {
    if (menuItem == null) {
      pnl.clear();
      return;
    }

    QMenu menu = this.getMenu();
    // 画出菜单项部分
    pnl.add(draw_pnlItem(menu));

    // 画出子菜单部分
    if (menu.hasChildren(menuItem)) {
      pnl.add(draw_pnlSubMenu());
    }
  }

  private Widget draw_pnlItem(QMenu menu) throws ClientBizException {
    pnlItem = new HorizontalPanel();
    pnlItem.setWidth("100%");
    pnlItem.setStyleName("rb-smi-item");

    lstnItem = new Listener_menuItem();

    imgPoint = new Image();
    imgPoint.setStyleName("rb-smi-item-point");
    imgPoint.setUrl(this.getPointImageUrl(menu));
    imgPoint.addClickListener(lstnItem);
    imgPoint.addMouseListener(lstnItem);
    pnlItem.add(imgPoint);
    pnlItem.setCellHeight(imgPoint, "100%");
    pnlItem.setCellVerticalAlignment(imgPoint, HorizontalPanel.ALIGN_MIDDLE);

    imgIcon = new Image();
    imgIcon.setWidth("16px");
    imgIcon.setHeight("16px");
    imgIcon.setStyleName("rb-smi-item-icon");
    imgIcon.addLoadListener(new Listener_imgIcon());
    imgIcon.setUrl(URL_ICON_DEFAULT);
    if (this.menuItem.getImage() != null)
      imgIcon.setUrl(GWTUtil.getStaticContentURL(this.menuItem.getImage()));
    imgIcon.setTitle(this.menuItem.getHint());
    imgIcon.addClickListener(lstnItem);
    imgIcon.addMouseListener(lstnItem);
    pnlItem.add(imgIcon);
    pnlItem.setCellHeight(imgIcon, "100%");
    pnlItem.setCellVerticalAlignment(imgIcon, HorizontalPanel.ALIGN_MIDDLE);

    htmlCaption = new HTML();
    htmlCaption.setText(this.menuItem.getCaption());
    htmlCaption.setTitle(this.menuItem.getHint());
    htmlCaption.setHeight("100%");
    htmlCaption.setWidth("100%");
    htmlCaption.setStyleName("rb-smi-item-caption");
    htmlCaption.addClickListener(lstnItem);
    htmlCaption.addMouseListener(lstnItem);
    pnlItem.add(htmlCaption);
    pnlItem.setCellHeight(htmlCaption, "100%");
    pnlItem.setCellWidth(htmlCaption, "100%");
    pnlItem.setCellVerticalAlignment(htmlCaption, HorizontalPanel.ALIGN_MIDDLE);

    // 如果当前菜单项是叶节点，则画出在新窗口中打开的按钮。
    if (!menu.hasChildren(menuItem)) {
      lstnNewWindow = new Listener_imgNewWindow();
      imgNewWindow = new Image();
      imgNewWindow.setUrl(URL_NEWWINDOW_BLANK);
      imgNewWindow.setTitle("在新窗口中打开");
      imgNewWindow.setStyleName("rb-smi-btn");
      imgNewWindow.addClickListener(lstnNewWindow);
      imgNewWindow.addMouseListener(lstnNewWindow);
      pnlItem.add(imgNewWindow);
      pnlItem.setCellVerticalAlignment(imgNewWindow, HorizontalPanel.ALIGN_MIDDLE);
    }

    return pnlItem;
  }

  private Widget draw_pnlSubMenu() throws ClientBizException {
    pnlSubMenu = new HorizontalPanel();
    pnlSubMenu.setWidth("100%");
    pnlSubMenu.setStyleName("rb-smi-submenu");
    pnlSubMenu.setVisible(this.expanded);

    lblIndent = new Label();
    lblIndent.setStyleName("rb-smi-submenu-indent");
    pnlSubMenu.add(lblIndent);

    wSubMenu = new SiteMenuCmpst(this);
    wSubMenu.refresh();
    pnlSubMenu.add(wSubMenu);

    return pnlSubMenu;
  }

  /** 取得用于imgPoint的图片URL */
  private String getPointImageUrl(QMenu menu) throws ClientBizException {
    if (menu.hasChildren(menuItem))
      return expanded ? "images/smi-expanded.gif" : "images/smi-collapsed.gif";
    else
      return "images/smi-leaf.gif";
  }

  private void click(boolean newWindow) {
    try {
      if (!this.expanded)
        wUpperMenu.expandItem(this);
      else
        this.collapse();

      this.getEntryPoint().clickSiteMenuItem(this.menuItem, newWindow);
    } catch (Exception e) {
      MessageBox.alert(Window.getTitle(), "点击菜单项时发生异常。<br>" + e.getMessage());
    }
  }

  private void refreshDisplayState() {
    if (this.hot) {
      pnlItem.setStyleName("rb-smi-item-hot");
      if (this.down)
        pnlItem.setStyleName("rb-smi-item-down");

      if (imgNewWindow != null) {
        imgNewWindow.setUrl(URL_NEWWINDOW);
        if (this.hot_newWindow) {
          imgNewWindow.setStyleName("rb-smi-btn-hot");
          if (this.down_newWindow)
            imgNewWindow.setStyleName("rb-smi-btn-down");
        }
      }

    } else {
      pnlItem.setStyleName("rb-smi-item");
      if (imgNewWindow != null) {
        imgNewWindow.setUrl(URL_NEWWINDOW_BLANK);
        imgNewWindow.setStyleName("rb-smi-btn");
      }
    }
  }

  private void mouseEnter() {
    this.getWMenu().setHotWItem(this, true);
  }

  private void mouseLeave() {
    this.getWMenu().setHotWItem(this, false);
  }

  private void mouseDown() {
    this.getWMenu().setDownWItem(this, true);
  }

  private void mouseUp() {
    this.getWMenu().setDownWItem(this, false);
  }

  private void mouseEnter_newWindow() {
    this.getWMenu().setHotWItem_newWindow(this, true);
    this.getWMenu().setHotWItem(this, true);
  }

  private void mouseLeave_newWindow() {
    this.getWMenu().setHotWItem_newWindow(this, false);
    this.getWMenu().setHotWItem(this, false);
  }

  private void mouseDown_newWindow() {
    this.getWMenu().setDownWItem_newWindow(this, true);
  }

  private void mouseUp_newWindow() {
    this.getWMenu().setDownWItem_newWindow(this, false);
  }

}
